import requests
import json
import re
from enum import Enum
from typing import Dict, List, Optional, Set

class TaskType(Enum):
    REPAIR = "报修"
    FEE_QUERY = "物业费查询"
    COMPLAINT = "投诉建议"
    OTHER = "其他"

class TaskNode:
    def __init__(self, task_type: TaskType, required_fields: Set[str], prompt: str):
        self.task_type = task_type
        self.required_fields = required_fields  # 此任务需要的信息字段
        self.prompt = prompt  # 系统提示词
        self.collected_data = {}  # 此任务已收集的数据
        
    def is_complete(self) -> bool:
        """检查此任务是否已收集所有必要信息"""
        return all(field in self.collected_data for field in self.required_fields)
        
    def update_data(self, field: str, value: str):
        """更新此任务收集的数据"""
        self.collected_data[field] = value

class CommunityAssistant:
    def __init__(self, api_key=None):
        self.api_url = "https://api.deepseek.com/v1/chat/completions"
        self.api_key = api_key
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }

        # 全局信息池，存储所有已收集的信息
        self.global_info = {
            "building_number": None,  # 楼栋号
            "unit_number": None,      # 单元号
            "room_number": None,      # 房间号
            "contact_info": None,     # 联系方式
            "owner_name": None        # 业主姓名
        }
        
        # 定义不同任务及其所需信息
        self.tasks = {
            TaskType.REPAIR: TaskNode(
                TaskType.REPAIR,
                {"building_number", "unit_number", "room_number", "problem_type", "problem_details", "contact_info"},
                """你是一个社区报修助手，负责引导用户提供报修所需的所有信息。
                报修流程分为以下步骤：
                1. 确认用户需要报修（例如房间灯坏了）
                2. 收集楼栋号
                3. 收集单元号
                4. 收集房间号
                5. 了解具体哪里坏了和详细情况
                6. 确认联系方式

                每次只询问一个信息点，除非用户主动提供多个信息。
                对话应该友好、专业，并引导用户逐步提供所有必要信息。
                当收集到所有信息后，确认信息是否正确，然后生成报修工单。"""
            ),
            TaskType.FEE_QUERY: TaskNode(
                TaskType.FEE_QUERY,
                {"building_number", "unit_number", "room_number", "owner_name"},
                """你是一个物业费查询助手，负责帮助用户查询物业费缴纳情况。
                需要收集以下信息：
                1. 楼栋号
                2. 单元号
                3. 房间号
                4. 业主姓名（用于验证身份）

                每次只询问一个信息点，除非用户主动提供多个信息。
                对话应该友好、专业，确认信息后查询物业费缴纳状态。"""
            ),
            TaskType.COMPLAINT: TaskNode(
                TaskType.COMPLAINT,
                {"building_number", "unit_number", "room_number", "complaint_details", "contact_info"},
                """你是一个投诉建议处理助手，负责帮助用户提交投诉或建议。
                需要收集以下信息：
                1. 楼栋号（可选）
                2. 单元号（可选）
                3. 房间号（可选）
                4. 投诉或建议的详细内容
                5. 联系方式

                对话应该友好、专业，确保准确理解用户的问题。"""
            )
        }
        
        # 当前活动任务和任务栈（用于挂起和恢复任务）
        self.current_task: Optional[TaskType] = None
        self.task_stack: List[TaskType] = []
        
        # 对话历史
        self.conversation_history = []

    def detect_task_intent(self, user_input: str) -> Optional[TaskType]:
        """检测用户输入中的任务意图"""
        user_input = user_input.lower()
        
        if any(word in user_input for word in ["报修", "坏了", "维修", "修理"]):
            return TaskType.REPAIR
        elif any(word in user_input for word in ["物业费", "缴费", "缴纳", "欠费"]):
            return TaskType.FEE_QUERY
        elif any(word in user_input for word in ["投诉", "建议", "意见", "不满"]):
            return TaskType.COMPLAINT
            
        return None

    def extract_info(self, text: str):
        """从用户输入中提取结构化信息并更新全局信息池"""
        # 提取楼栋号（例如：1栋、2号楼等）
        building_match = re.search(r'(\d+)[栋号楼]', text)
        if building_match:
            self.global_info['building_number'] = building_match.group(1)

        # 提取单元号（例如：1单元、单元2等）
        unit_match = re.search(r'(\d+)[单元元]|单元\s*(\d+)', text)
        if unit_match:
            self.global_info['unit_number'] = unit_match.group(1) or unit_match.group(2)

        # 提取房间号（例如：101室、房间202等）
        room_match = re.search(r'(\d+)[室号]|房间\s*(\d+)', text)
        if room_match:
            self.global_info['room_number'] = room_match.group(1) or room_match.group(2)

        # 提取业主姓名（简单匹配2-4个中文字符）
        name_match = re.search(r'[我俺咱]叫(\S{2,4})', text)
        if not name_match:
            name_match = re.search(r'姓名[是叫]?(\S{2,4})', text)
        if name_match:
            self.global_info['owner_name'] = name_match.group(1)

        # 提取联系方式（手机号）
        phone_match = re.search(r'1[3-9]\d{9}', text)
        if phone_match:
            self.global_info['contact_info'] = phone_match.group(0)

        # 检查是否包含问题描述关键词
        problem_keywords = ['灯坏了', '漏水', '断电', '堵塞', '损坏', '坏了', '故障']
        for keyword in problem_keywords:
            if keyword in text:
                if self.current_task and self.current_task in self.tasks:
                    self.tasks[self.current_task].update_data('problem_type', keyword)
                break

    def sync_task_data(self):
        """将全局信息同步到当前任务中"""
        if not self.current_task:
            return
            
        task_node = self.tasks[self.current_task]
        
        # 将全局信息中当前任务需要的字段同步到任务数据中
        for field in task_node.required_fields:
            if field in self.global_info and self.global_info[field] is not None:
                task_node.update_data(field, self.global_info[field])

    def get_missing_info(self) -> List[str]:
        """获取当前任务还缺少的信息字段"""
        if not self.current_task:
            return []
            
        task_node = self.tasks[self.current_task]
        missing = []
        
        for field in task_node.required_fields:
            if field not in task_node.collected_data or task_node.collected_data[field] is None:
                # 将字段名转换为中文描述
                field_names = {
                    "building_number": "楼栋号",
                    "unit_number": "单元号",
                    "room_number": "房间号",
                    "problem_type": "问题类型",
                    "problem_details": "问题详情",
                    "contact_info": "联系方式",
                    "owner_name": "业主姓名",
                    "complaint_details": "投诉内容"
                }
                missing.append(field_names.get(field, field))
                
        return missing

    def call_deepseek_api(self, user_message: str, system_prompt: str = None) -> str:
        """
        调用DeepSeek API获取回复
        """
        # 准备消息历史
        messages = []
        
        # 添加系统提示
        if system_prompt:
            messages.append({"role": "system", "content": system_prompt})
        
        # 添加对话历史
        messages.extend(self.conversation_history[-6:])  # 只保留最近6条历史
        
        # 添加当前用户消息
        messages.append({"role": "user", "content": user_message})

        payload = {
            "model": "deepseek-chat",
            "messages": messages,
            "temperature": 0.3,
            "max_tokens": 500
        }

        try:
            response = requests.post(self.api_url, headers=self.headers, data=json.dumps(payload))
            response.raise_for_status()
            result = response.json()
            assistant_reply = result['choices'][0]['message']['content']

            # 更新对话历史
            self.conversation_history.append({"role": "user", "content": user_message})
            self.conversation_history.append({"role": "assistant", "content": assistant_reply})

            return assistant_reply

        except Exception as e:
            return f"调用API时出错: {str(e)}"

    def start_task(self, task_type: TaskType):
        """开始一个新任务"""
        if self.current_task:
            # 挂起当前任务
            self.task_stack.append(self.current_task)
            
        self.current_task = task_type
        # 同步全局信息到新任务
        self.sync_task_data()
        
        # 获取任务提示
        task_prompt = self.tasks[task_type].prompt
        
        # 添加任务引导语
        if task_type == TaskType.REPAIR:
            greeting = "好的，我来帮您处理报修问题。"
        elif task_type == TaskType.FEE_QUERY:
            greeting = "好的，我来帮您查询物业费缴纳情况。"
        elif task_type == TaskType.COMPLAINT:
            greeting = "好的，我来记录您的投诉或建议。"
        else:
            greeting = "好的，我来帮助您。"
            
        # 添加缺失信息提示
        missing_info = self.get_missing_info()
        if missing_info:
            greeting += f" 还需要您提供以下信息：{', '.join(missing_info)}。请先告诉我{missing_info[0]}吧。"
        else:
            greeting += " 请描述您遇到的问题。"
            
        return greeting

    def complete_current_task(self):
        """完成当前任务并生成结果"""
        if not self.current_task:
            return "当前没有正在进行的任务。"
            
        task_node = self.tasks[self.current_task]
        
        if not task_node.is_complete():
            return "任务信息还不完整，无法完成。"
            
        # 根据任务类型生成不同的结果
        if self.current_task == TaskType.REPAIR:
            result = self.generate_repair_order()
        elif self.current_task == TaskType.FEE_QUERY:
            result = self.generate_fee_query_result()
        elif self.current_task == TaskType.COMPLAINT:
            result = self.generate_complaint_result()
        else:
            result = "任务已完成。"
            
        # 如果有挂起的任务，询问是否继续
        if self.task_stack:
            previous_task = self.task_stack.pop()
            result += f"\n您之前正在办理{previous_task.value}业务，需要继续吗？"
            self.current_task = previous_task
        else:
            self.current_task = None
            
        return result

    def generate_repair_order(self) -> str:
        """生成报修工单"""
        task_node = self.tasks[TaskType.REPAIR]
        
        repair_order = {
            "工单类型": "物业报修",
            "报修时间": "2025-09-09 10:30:00",  # 应使用实际时间
            "楼栋号": task_node.collected_data.get('building_number', '未知'),
            "单元号": task_node.collected_data.get('unit_number', '未知'),
            "房间号": task_node.collected_data.get('room_number', '未知'),
            "问题类型": task_node.collected_data.get('problem_type', '未知'),
            "问题详情": task_node.collected_data.get('problem_details', task_node.collected_data.get('problem_type', '未知')),
            "联系方式": task_node.collected_data.get('contact_info', '未知'),
            "工单状态": "待处理"
        }

        return f"报修工单已生成：\n{json.dumps(repair_order, ensure_ascii=False, indent=2)}"

    def generate_fee_query_result(self) -> str:
        """生成物业费查询结果"""
        task_node = self.tasks[TaskType.FEE_QUERY]
        
        # 模拟查询结果 - 实际应连接数据库
        fee_status = {
            "楼栋号": task_node.collected_data.get('building_number', '未知'),
            "单元号": task_node.collected_data.get('unit_number', '未知'),
            "房间号": task_node.collected_data.get('room_number', '未知'),
            "业主姓名": task_node.collected_data.get('owner_name', '未知'),
            "缴费状态": "已缴纳",
            "最近缴费日期": "2025-08-15",
            "下次缴费截止日期": "2025-12-31"
        }

        return f"物业费查询结果：\n{json.dumps(fee_status, ensure_ascii=False, indent=2)}"

    def generate_complaint_result(self) -> str:
        """生成投诉建议处理结果"""
        task_node = self.tasks[TaskType.COMPLAINT]
        
        complaint_record = {
            "投诉类型": "业主投诉",
            "楼栋号": task_node.collected_data.get('building_number', '未知'),
            "单元号": task_node.collected_data.get('unit_number', '未知'),
            "房间号": task_node.collected_data.get('room_number', '未知'),
            "投诉内容": task_node.collected_data.get('complaint_details', '未知'),
            "联系方式": task_node.collected_data.get('contact_info', '未知'),
            "处理状态": "已记录，将在3个工作日内回复"
        }

        return f"投诉建议已记录：\n{json.dumps(complaint_record, ensure_ascii=False, indent=2)}"

    def run_conversation(self):
        """运行对话流程"""
        print("社区物业助手：您好！我是社区物业助手，可以帮您处理报修、查询物业费、提交投诉建议等。请问有什么需要帮助的吗？")

        while True:
            user_input = input("您：").strip()
            
            if not user_input:
                continue

            # 如果用户输入退出命令，则结束对话
            if user_input.lower() in ['退出', '结束', 'quit', 'exit']:
                print("社区物业助手：感谢您使用物业服务，再见！")
                break

            # 提取用户输入中的信息
            self.extract_info(user_input)
            
            # 检测用户是否有切换任务的意图
            new_task = self.detect_task_intent(user_input)
            
            if new_task and new_task != self.current_task:
                # 用户想要开始新任务
                response = self.start_task(new_task)
                print(f"社区物业助手：{response}")
                continue
                
            # 同步全局信息到当前任务
            if self.current_task:
                self.sync_task_data()
                
                # 检查当前任务是否已完成
                if self.tasks[self.current_task].is_complete():
                    response = self.complete_current_task()
                    print(f"社区物业助手：{response}")
                    continue
                    
                # 调用API获取回复
                system_prompt = self.tasks[self.current_task].prompt
                response = self.call_deepseek_api(user_input, system_prompt)
                print(f"社区物业助手：{response}")
            else:
                # 没有当前任务，询问用户想要办理什么业务
                response = self.call_deepseek_api(
                    user_input, 
                    "你是社区物业助手，可以帮用户处理报修、查询物业费、提交投诉建议等。请询问用户想要办理什么业务。"
                )
                print(f"社区物业助手：{response}")


# 使用示例
if __name__ == "__main__":
    assistant = CommunityAssistant("sk-8751514eba5c42a0bfb3fe083b09bf6e")
    assistant.run_conversation()